﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
using System.Configuration;
using System.Data.OleDb;
using System.Data;
using System.Text.RegularExpressions;
using System.Xml;
using System.Data.SqlClient;
using System.Collections.Specialized;
using HTSwitchServerNamespace.ar.com.horsetrack;


using HTMailSenderNamespace;
using ProtocoloNameSpace;
using GoogleClassNamespace;

using System.Runtime.Serialization;
using System.Linq;
using System.Runtime.Serialization.Json;
using Newtonsoft.Json;
using HTSwitchServerNamespace;
using System.Xml.XPath;
using System.Xml.Linq;
using HTSwitchMailHandlerNameSpace;
using HTSwitchServerNamespace.Util;
using HTSwitchServerNamespace.Protocols;
using MobileManagement.Library;


///Ultima modificación: 31-5-12
///Versión: v1.00.01
///Programmer: FD

namespace HTSwitchServerNamespace
{
  public class CHTSwitchServer
    {
        #region Declaracion de variables
            TcpListener listener;
		    private Thread mainThread;
            private Thread mantenimientoThread;
            private Thread mantenimientoThreadDiario;
            private Thread ThreadControldeNuevosUsuarios;
           

		    private Int32 nListenTcpPort;
		    private IPAddress IpAddressServer;
		    private Int32 nTimeoutCommSec;
		    private bool bIsListening;
            private bool bIsRunningMantenimientoDiario;
            private bool bIsRunningMantenimientoPrioritario;
            private bool bIsRunningControldeNuevosUsuarios;
        
            private CHTSwitchProtocol objHTSwitchProtocol;
        #endregion
        /// <summary>
		/// Retorna si el servidor esta escuchando requerimientos TCP de los caballos
		/// </summary>
		/// <returns> Booleano</returns>
		public bool IsListening()
		{
			return bIsListening;
		}
        public bool isRunningMantenimientoDiario()
        {
            return bIsRunningMantenimientoDiario;
        }
        public bool isRunningMantenimientoPrioritario()
        {
            return bIsRunningMantenimientoPrioritario;
        }
        public bool isRunningControldeNuevosUsuarios()
        {
            return bIsRunningControldeNuevosUsuarios;
        }       

		#region Constructor
		/// <summary>
		/// Constructor por defecto
		/// </summary>
		public CHTSwitchServer()
		{
			listener = null;
			Init();
			CLogger.Init();
            
           
		}
		#endregion


		#region Metodos Publicos
		/// <summary>
		/// Init lee del app.config las distintas "keys", cargando los fields de la clase con los valores correspondientes
		/// </summary>
		public void Init()
		{
			string strField;
			NameValueCollection appSettings = ConfigurationManager.AppSettings;

			foreach (String strEntry in appSettings.AllKeys)
			{
				switch (strEntry)
				{
					case "serverTCPPort":
						strField = appSettings[strEntry];
						if (Int32.TryParse(strField, out nListenTcpPort) == false)
							nListenTcpPort = 5125;
						break;
					case "serverIPAddress":
						strField = appSettings[strEntry];
						if (IPAddress.TryParse(strField.ToString(), out IpAddressServer) == false)
							IpAddressServer = IPAddress.Parse("127.0.0.1");
						break;
					case "serverTimeoutSec":
						strField = appSettings[strEntry];
						if (Int32.TryParse(strField, out nTimeoutCommSec) == false)
							nTimeoutCommSec = 30;
						break;					
				}
			}
		}


		#endregion

		#region Perform Trans
		/// <summary>
		/// Es el worker que procesa el requerimiento
		/// </summary>
		/// <param name="client">Objeto del tipo TcpClient con el socket conectado listo para recibir</param>
		private void HandleMessageComm(object client)
		{
           

            ///Declaración de Variables//////////////////////////////
			TcpClient tcpClient = ((TcpClient)client);                           
            ProtocoloComunicacion objProtocoloComunic = new ProtocoloComunicacion();
              IProtocol objProtocoloComun;


            ///COMIENZO DEL PROGRAMA////////////////////////////////////
            try
			{
				CLogger.Append("Connection Open from HORSE: " + tcpClient.Client.RemoteEndPoint.ToString(), CLogger.COMM);
                
                NetworkStream netStream = tcpClient.GetStream();
                byte[] byteArrBuffer = new byte[tcpClient.ReceiveBufferSize];
                int bytesRead = 0;            
                //do
                //{
                    try
                    {
                        netStream.ReadTimeout = 60000; /// 1 Minuto
                        CLogger.Append("Receiving from HORSE (TO = " + netStream.ReadTimeout.ToString() + " ms) ", CLogger.COMM);               
                         netStream.ReadTimeout = -1; /// 2 Minuto

                         bytesRead = netStream.Read(byteArrBuffer, 0, (int)tcpClient.ReceiveBufferSize);//HZ

                         if (bytesRead == 0)
                         {
                             CLogger.Append("Received ZERO bytes, going to Read() again... ", CLogger.ERROR);
                           
                         }
                         else
                         {
                             if (tcpClient.Connected == false)
                             {
                                 CLogger.Append("Connection Close from HORSE", CLogger.COMM);
                                 //throw new Exception("Connection Close from HORSE");
                             }
                             else
                             {
                                 objProtocoloComun = objProtocoloComunic.ObtenerProtocolo(Encoding.UTF8.GetString(byteArrBuffer, 0, bytesRead)); //HZ //FD v1.00.01
                                 
                                 if (objProtocoloComun.ObteneryEnviarDatosDelDispositivo(Encoding.UTF8.GetString(byteArrBuffer, 0, bytesRead),tcpClient) == true)                             //HZ  //FD v1.00.01
                                 {
                                    
                                   
                                     //CLogger.Append("DATOS ENVIADOS CORRECTAMENTE -***", CLogger.INFO);
                                     //Envio ok
                                 }
                                 else 
                                 {
                                     CLogger.Append("FALLO EL ENVIO DE DATOS - ENVIO FALSE", CLogger.INFO);
                                    // fallo
                                 }                                 
                             }
                         }
                    }
                    catch(IOException ioex)
                    {
                        CLogger.Append("Conection TIMEOUT: " + ioex.Message, CLogger.ERROR);                     
                        throw ;
                    }   
			}
			catch (Exception ex)
			{
				CLogger.Append("ERROR GENERAL: #Algo Fallo - Revisar Metodos:  "+ ex.Message, CLogger.ERROR);
                CLogger.Append("EXCEPTION: STACK TRACE: " + ex.StackTrace, CLogger.ERROR);
			}
			finally
			{
                tcpClient.Close();
			}
            
		}
        #endregion

        #region Trhead Metodos Server
        /// <summary>
        /// LanzarServer lanza el thread que recibe las transacciones del switch y que envía las peticiones al Web Service
        /// </summary>
        public void LanzarServer()
        {
            // Lanza el proceso principal
            string strVersion = "1.00.01 - (31/5/2012)";
            CLogger.Append(" Lanzamiento del servicio HTSwitch " + strVersion, CLogger.COMM);
            mainThread = new Thread(new ThreadStart(this.RunServer));
            mainThread.Start();
        }
        
        /// <summary>
		/// Frena el thread de escucha de requerimientos del switch
		/// </summary>
		public void StopServer()
		{
			if (bIsListening == true)
			{
				bIsListening = false;
				CLogger.Append(" Detencion del servicio", CLogger.COMM);
				listener.Stop();
				mainThread.Join();
                objHTSwitchProtocol = null;
			}
		}
		/// <summary>
		/// Inicia el servidor de escucha TCP en el puerto definido en el app.config, leido del método Init()
		/// </summary>
		public void RunServer()
		{
			try
			{
				CLogger.Append(" IpAddressServer: " + IpAddressServer.ToString() + " Listen Tcp Port: " + nListenTcpPort, CLogger.INFO);

				objHTSwitchProtocol = new CHTSwitchProtocol();
                objHTSwitchProtocol.LevantarServicio();

				listener = new TcpListener(IpAddressServer, nListenTcpPort);
				listener.Start();
				bIsListening = true;

                
				do
				{
					if (!listener.Pending())
					{
						Thread.Sleep(500);
						continue;
					}

					//blocks until a client has connected to the server
					TcpClient tcpclient = listener.AcceptTcpClient();
					CLogger.Append(" TcpClient: " + tcpclient.ToString(), CLogger.INFO);

					// create a thread to handle communication 
					// with connected client
					tcpclient.ReceiveTimeout = nTimeoutCommSec * 1000;
					tcpclient.SendTimeout = nTimeoutCommSec * 1000;

					// queue a request to take care of the client
					ThreadPool.QueueUserWorkItem(new WaitCallback(HandleMessageComm),tcpclient);					
					
				}while (bIsListening);

			}
			catch (Exception ex)
			{
				CLogger.Append("Error in: " + ex.Source + " Message: " + ex.Message, CLogger.ERROR);
			}
		}
		#endregion

        #region Mantenmiento Alta Prioridadd
        public void lanzarMantenimientoPrioritario()
        {
            //Lanza el proceso principal
            string strVersion = "1.0.0 - (06/10/2011)";
            CLogger.Append(" Lanzamiento del servicio de Mantenimiento " + strVersion, CLogger.COMM);
            mantenimientoThread = new Thread(new ThreadStart(this.RunServerMantenimientoPrioritario));
            mantenimientoThread.Start();

        }


        /// <summary>
        /// Frena el thread del mantenimiento prioritario
        /// </summary>
        public void stopServerMantenimientoPrioritario()
        {
            if (bIsRunningMantenimientoPrioritario == true)
            {
                bIsRunningMantenimientoPrioritario = false;
                CLogger.Append(" Detencion del servicio mantenimiento prioritario", CLogger.COMM);
                mantenimientoThread.Join();
            }
        }

		/// <summary>
		/// Inicia el mantenimiento prioritario
		/// </summary>
		public void RunServerMantenimientoPrioritario()
        {
          // List<Alerta> lstAlertas = new List<Alerta>();
              HTSwitchServerNamespace.ar.com.horsetrack.HorsetrackWebService objWebService = new HTSwitchServerNamespace.ar.com.horsetrack.HorsetrackWebService();           
            try
			{
                bIsRunningMantenimientoPrioritario = true;

                while (bIsRunningMantenimientoPrioritario)
                {
                    objWebService.limpiarDatosTrazabilidad();
                    procesoAlarmas();
                    for(int i=0; i < 3600; i++)
                    {
                        Thread.Sleep(1000);
                        if (!bIsRunningMantenimientoPrioritario)
                        {
                            break;
                        }
                    }
                }
			}
			catch (Exception ex)
			{
				CLogger.Append("Error in: " + ex, CLogger.ERROR);
			}
		}


        public void procesoAlarmas()
        {
            Alerta[] objArrAlertas;        
            HTSwitchServerNamespace.ar.com.horsetrack.HorsetrackWebService objWebService = new HTSwitchServerNamespace.ar.com.horsetrack.HorsetrackWebService();
            List<Alerta> lstAlertasProcesadas = new List<Alerta>();

            objArrAlertas = objWebService.obtenerAlarmasDisponibles();
           if (objArrAlertas.Length != 0)
            {

                foreach (Alerta objNuevaAlerta in objArrAlertas)
                {
                    CLogger.Append("Nueva Alerta: " + objNuevaAlerta.strModoAlerta, CLogger.INFO);
                   

                       string[] strArrModoAlerta=objNuevaAlerta.strModoAlerta.Split (new char[]  { ':' });
                                            
                   switch (strArrModoAlerta[0])
                   {
                       case "MAIL":
                          enviarAlertaAlMail(strArrModoAlerta[1]);

                           break;
                       case "SMS":
                           //enviarAlertaSMS();
                           break;
                       default:

                           break;
                   
                   }
                    lstAlertasProcesadas.Add(objNuevaAlerta);                                       
                }
                objWebService.limpiarAlertasProcesadas(lstAlertasProcesadas.ToArray());
            }
            else 
            { 
            }         
        }

        public void enviarAlertaAlMail(string strMailAlerta)
        {
            string[] strClientHost = new string[5];

           // strClientHost[0] = "mail.zbctech.com.ar";
            strClientHost[0] = "mail.horsetrack.com.ar";
            strClientHost[1] = "25";
            strClientHost[2] = strMailAlerta;   //Dirección de mail

            HTMailSenderNamespace.SimpleAsynchronousExample.MailAlerta(strClientHost);
        }
		#endregion

        #region Mantenmiento Baja Prioridadd

        public void lanzarMantenimientoDiario()
        {
            // Lanza el proceso principal
            string strVersion = "1.00.01 - (06/10/2011)";
            CLogger.Append(" Lanzamiento de Mantenimiento Diario" + strVersion, CLogger.COMM);
            mantenimientoThreadDiario = new Thread(new ThreadStart(this.RunServerMantenimientoDiario));
            mantenimientoThreadDiario.Start();         
                
        }
        /// <summary>
        /// Frena el thread de limpiador del mantenimiento diario
        /// </summary>
        public void stopServerMantenimientoDiario()
        {
            if (bIsRunningMantenimientoDiario == true)
            {
                bIsRunningMantenimientoDiario = false;
                mantenimientoThreadDiario.Join();
                CLogger.Append(" Detencion del servicio mantenimiento diario", CLogger.COMM);
            }
        }

        /// <summary>
        /// Inicia el mantenimiento diario, todos los metodos de aqui se ejecutaran cada un día()
        /// </summary>
        public void RunServerMantenimientoDiario()
        {

            // List<Alerta> lstAlertas = new List<Alerta>();
            HTSwitchServerNamespace.ar.com.horsetrack.HorsetrackWebService objWebServiceDiario = new HTSwitchServerNamespace.ar.com.horsetrack.HorsetrackWebService();
            try
            {
                bIsRunningMantenimientoDiario = true;
                while (bIsRunningMantenimientoDiario)
                {
                    //objWebServiceDiario.limpiarDatosTrazabilidad();
                    CLogger.Append(" SE HA INICIADO UN NUEVO DIA - Server vivo", CLogger.COMM);

                    for (int i = 0; i < 86400; i++)
                    {
                       
                        Thread.Sleep(1000);
                        if (!bIsRunningMantenimientoDiario)
                        {
                          
                            break;
                        }
                    }

                   
                }
            }
            catch (Exception ex)
            {
                CLogger.Append("Error in: " + ex, CLogger.ERROR);
            }
        }
        #endregion

        #region Control de Nuevos Usuarios Por Mail

        public void lanzarControldeNuevosUsuarios()
        {
            // Lanza el proceso principal
            string strVersion = "1.00.01 - (07/09/2012)";
            CLogger.Append(" Lanzamiento de Control de Nuevos Usuarios por Mail" + strVersion, CLogger.COMM);
            ThreadControldeNuevosUsuarios = new Thread(new ThreadStart(this.RunControldeNuevosUsuarios));
            ThreadControldeNuevosUsuarios.Start();

        }
        /// <summary>
        /// Frena el thread de control de neuvos usuarios
        /// </summary>
        public void stopControldeNuevosUsuarios()
        {
            if (bIsRunningControldeNuevosUsuarios == true)
            {
                bIsRunningControldeNuevosUsuarios = false;
                ThreadControldeNuevosUsuarios.Join();
                CLogger.Append(" Detencion del servicio Control de Nuevos Usuarios", CLogger.COMM);
            }
        }

        /// <summary>
        /// Inicia el control de nuevos usuarios
        /// </summary>
        public void RunControldeNuevosUsuarios()
        {

            MailHandler objMailHandler = new MailHandler();

            HTSwitchServerNamespace.ar.com.horsetrack.HorsetrackWebService objWebServiceControl = new HTSwitchServerNamespace.ar.com.horsetrack.HorsetrackWebService();
            try
            {
                bIsRunningControldeNuevosUsuarios = true;
                while (bIsRunningControldeNuevosUsuarios)
                {
                    objMailHandler.ControlMails("controlesyseguimiento@gmail.com", "fabiohernan", "imap.gmail.com","WEBS");
                    //objMailHandler.ControlMails("controlesyseguimiento@gmail.com", "fabiohernan", "imap.gmail.com", "ML");

                  //  objMailHandler.ControlMails("healthsolutionargentina@gmail.com", "fabiohernan", "imap.gmail.com", "WEBS");
                   // objMailHandler.ControlMails("celososycelosas@hotmail.com", "fabiohernan1", "pop3.live.com","ML");
                    for (int i = 0; i < 180; i++)
                    {
                        Thread.Sleep(1000);
                        if (!bIsRunningControldeNuevosUsuarios)
                        {
                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                CLogger.Append("Error in: " + ex, CLogger.ERROR);
            }
        }
        #endregion

        #region Control de alarmas y moviles en el sistema
        public void LanzarControAlarmasMoviles()
        {
            try
            {
                
                /*
                // Create an event to signal the timeout count threshold in the 
                // timer callback.
                AutoResetEvent autoEvent = new AutoResetEvent(false);

                TimerClass statusChecker = new TimerClass(10);

                // Create an inferred delegate that invokes methods for the timer.
                TimerCallback tcb = statusChecker.CheckStatus;

                // Create a timer that signals the delegate to invoke  
                // CheckStatus after one second, and every 1/4 second  
                // thereafter.
                Console.WriteLine("{0} Creating timer.\n",DateTime.Now.ToString("h:mm:ss.fff"));
                
                Timer stateTimer = new Timer(tcb, autoEvent, 7200000, 7200000);

                // When autoEvent signals, change the period to every 
                // 1/2 second.
               /* autoEvent.WaitOne(5000, false);
                stateTimer.Change(0, 500);
                Console.WriteLine("\nChanging period.\n");

                // When autoEvent signals the second time, dispose of  
                // the timer.
                autoEvent.WaitOne(5000, false);
                stateTimer.Dispose();
                Console.WriteLine("\nDestroying timer.");
                * */

                MobileManagementDoing.DropTable();
                MobileManagementDoing.MobileManagement_DoWork_Start();
               

            }
            catch(Exception ex)
            {
                CLogger.Append("[LanzarControAlarmasMoviles] ERROR EXCEPTION Control de alarmas y moviles: "+ ex, CLogger.ERROR);
            }
        }
        #endregion

        public void stopControAlarmasMoviles()
        {

            MobileManagementDoing.MobileManagement_DoWork_Stop();
        }
    }
}
